package requests

import (
	"fmt"
	"gohub/app/models/role"
	"gohub/app/requests/validators"
	"gohub/pkg/auth"
	"gohub/pkg/database"
	"gohub/pkg/helpers"
	"gohub/pkg/response"
	"mime/multipart"
	"os/user"
	"regexp"
	"time"

	"github.com/gin-gonic/gin"
	"github.com/thedevsaddam/govalidator"
)

func init() {
	// 1. 手机号验证规则
	govalidator.AddCustomRule("mobile", func(field string, rule string, message string, value interface{}) error {
		mobile, ok := value.(string)
		if !ok {
			return fmt.Errorf("手机号必须是字符串类型")
		}

		// 更严格的手机号验证
		if !regexp.MustCompile(`^1[3-9]\d{9}$`).MatchString(mobile) {
			if message != "" {
				return fmt.Errorf(message)
			}
			return fmt.Errorf("手机号格式不正确")
		}
		return nil
	})

	// 2. 可以添加其他自定义规则
	govalidator.AddCustomRule("datetime", func(field string, rule string, message string, value interface{}) error {
		dateStr, ok := value.(string)
		if !ok {
			return fmt.Errorf("日期必须是字符串")
		}

		if _, err := time.Parse("2006-01-02", dateStr); err != nil {
			if message != "" {
				return fmt.Errorf(message)
			}
			return fmt.Errorf("日期格式应为 YYYY-MM-DD")
		}
		return nil
	})
}

type UserUpdateProfileRequest struct {
	Name         string `valid:"name" json:"name"`
	City         string `valid:"city" json:"city"`
	Introduction string `valid:"introduction" json:"introduction"`
}

func UserUpdateProfile(data interface{}, c *gin.Context) map[string][]string {

	// 查询用户名重复时，过滤掉当前用户 ID
	uid := auth.CurrentUID(c)
	rules := govalidator.MapData{
		"name":         []string{"required", "alpha_num", "between:3,20", "not_exists:users,name," + uid},
		"introduction": []string{"min_cn:4", "max_cn:240"},
		"city":         []string{"min_cn:2", "max_cn:20"},
	}

	messages := govalidator.MapData{
		"name": []string{
			"required:用户名为必填项",
			"alpha_num:用户名格式错误，只允许数字和英文",
			"between:用户名长度需在 3~20 之间",
			"not_exists:用户名已被占用",
		},
		"introduction": []string{
			"min_cn:描述长度需至少 4 个字",
			"max_cn:描述长度不能超过 240 个字",
		},
		"city": []string{
			"min_cn:城市需至少 2 个字",
			"max_cn:城市不能超过 20 个字",
		},
	}

	return validate(data, rules, messages)
}

type UserUpdateEmailRequest struct {
	Email      string `json:"email,omitempty" valid:"email"`
	VerifyCode string `json:"verify_code,omitempty" valid:"verify_code"`
}

func UserUpdateEmail(data interface{}, c *gin.Context) map[string][]string {

	currentUser := auth.CurrentUser(c)
	rules := govalidator.MapData{
		"email": []string{
			"required", "min:4",
			"max:30",
			"email",
			"not_exists:users,email," + currentUser.GetStringID(),
			"not_in:" + currentUser.Email,
		},
		"verify_code": []string{"required", "digits:6"},
	}

	messages := govalidator.MapData{
		"email": []string{
			"required:Email 为必填项",
			"min:Email 长度需大于 4",
			"max:Email 长度需小于 30",
			"email:Email 格式不正确，请提供有效的邮箱地址",
			"not_exists:Email 已被占用",
			"not_in:新的 Email 与老 Email 一致",
		},
		"verify_code": []string{
			"required:验证码答案必填",
			"digits:验证码长度必须为 6 位的数字",
		},
	}

	errs := validate(data, rules, messages)
	_data := data.(*UserUpdateEmailRequest)
	errs = validators.ValidateVerifyCode(_data.Email, _data.VerifyCode, errs)

	return errs
}

type UserUpdatePhoneRequest struct {
	Phone      string `json:"phone,omitempty" valid:"phone"`
	VerifyCode string `json:"verify_code,omitempty" valid:"verify_code"`
}

func UserUpdatePhone(data interface{}, c *gin.Context) map[string][]string {

	currentUser := auth.CurrentUser(c)
	rules := govalidator.MapData{
		"phone": []string{
			"required",
			"digits:11",
			"not_exists:users,phone," + currentUser.GetStringID(),
			"not_in:" + currentUser.Mobile,
		},
		"verify_code": []string{"required", "digits:6"},
	}

	messages := govalidator.MapData{
		"phone": []string{
			"required:手机号为必填项，参数名称 phone",
			"digits:手机号长度必须为 11 位的数字",
			"not_exists:手机号已被占用",
			"not_in:新的手机与老手机号一致",
		},
		"verify_code": []string{
			"required:验证码答案必填",
			"digits:验证码长度必须为 6 位的数字",
		},
	}

	errs := validate(data, rules, messages)
	_data := data.(*UserUpdatePhoneRequest)
	errs = validators.ValidateVerifyCode(_data.Phone, _data.VerifyCode, errs)

	return errs
}

type UserUpdatePasswordRequest struct {
	Password           string `valid:"password" json:"password,omitempty"`
	NewPassword        string `valid:"new_password" json:"new_password,omitempty"`
	NewPasswordConfirm string `valid:"new_password_confirm" json:"new_password_confirm,omitempty"`
}

func UserUpdatePassword(data interface{}, c *gin.Context) map[string][]string {

	rules := govalidator.MapData{
		"password":             []string{"required", "min:6"},
		"new_password":         []string{"required", "min:6"},
		"new_password_confirm": []string{"required", "min:6"},
	}

	messages := govalidator.MapData{
		"password": []string{
			"required:密码为必填项",
			"min:密码长度需大于 6",
		},
		"new_password": []string{
			"required:密码为必填项",
			"min:密码长度需大于 6",
		},
		"new_password_confirm": []string{
			"required:确认密码框为必填项",
			"min:确认密码长度需大于 6",
		},
	}

	// 确保 comfirm 密码正确
	errs := validate(data, rules, messages)
	_data := data.(*UserUpdatePasswordRequest)
	errs = validators.ValidatePasswordConfirm(_data.NewPassword, _data.NewPasswordConfirm, errs)

	return errs
}

type UserUpdateAvatarRequest struct {
	Avatar *multipart.FileHeader `valid:"avatar" form:"avatar"`
}

func UserUpdateAvatar(data interface{}, c *gin.Context) map[string][]string {

	rules := govalidator.MapData{
		// size 的单位为 bytes
		// - 1024 bytes 为 1kb
		// - 1048576 bytes 为 1mb
		// - 20971520 bytes 为 20mb
		"file:avatar": []string{"ext:png,jpg,jpeg", "size:20971520", "required"},
	}

	messages := govalidator.MapData{
		"file:avatar": []string{
			"ext:ext头像只能上传 png, jpg, jpeg 任意一种的图片",
			"size:头像文件最大不能超过 20MB",
			"required:必须上传图片",
		},
	}

	return validateFile(c, data, rules, messages)
}

// ImportUserRequest 导入用户的请求参数
type ImportUserItem struct {
	Username string `json:"username" binding:"required,min=2,max=20"`
	Mobile   int    `json:"mobile" binding:"required"`
	Role     string `json:"role" binding:"required"`
	OpenTime string `json:"openTime" binding:"required,datetime=2006-01-02"`
}

// 纯数组的请求结构
type ImportUserRequest []ImportUserItem

func ValidateImportUser(c *gin.Context) (*ImportUserRequest, map[string]string, bool) {
	var request ImportUserRequest

	// 1. 绑定JSON数据
	if err := c.ShouldBindJSON(&request); err != nil {
		response.BadRequest(c, err, "请求解析错误，请确认请求格式是否正确。上传文件请使用 multipart 标头，参数请使用 JSON 格式。")
		return nil, nil, false
	}

	// 2. 批量查询角色
	var roles []role.Role
	if err := database.DB.Find(&roles).Error; err != nil {
		return nil, nil, false
	}

	// 3. 构建角色映射表
	roleMap := make(map[string]string, len(roles))
	for _, role := range roles {
		roleMap[role.Title] = role.GetStringID()
	}

	// 4. 验证每个用户项
	for i, row := range request {
		// 验证角色是否存在
		if _, ok := roleMap[row.Role]; !ok {
			validators.AddError(c, fmt.Sprintf("[%d].role", i), "角色不存在")
		}

		if !regexp.MustCompile(`^1[3-9]\d{9}$`).MatchString(helpers.IntToString(row.Mobile)) {
			validators.AddError(c, fmt.Sprintf("[%d].mobile", i), "手机号格式不正确")
		}

		// 验证手机号唯一性
		var count int64
		database.DB.Model(&user.User{}).Where("mobile = ?", row.Mobile).Count(&count)
		if count > 0 {
			validators.AddError(c, fmt.Sprintf("[%d].mobile", i), "手机号已存在")
		}
	}

	if validators.HasErrors(c) {
		return nil, nil, false
	}

	return &request, roleMap, true
}
